# -*- coding: utf-8 -*-
"""
-------------------------------------------------
File Name： column_sort_util
Description :
Author : 'li'
date： 2020/11/3
-------------------------------------------------
Change Activity:
2020/11/3:
-------------------------------------------------
"""

import copy
import random

from ml.cv.util.distance import get_distance


class ColumnSortUtil:
    def __init__(self, text_area_descriptions, max_interval=100):
        """

        :param text_area_descriptions:
        """
        self.max_interval = max_interval
        self.original_text_area_descriptions = text_area_descriptions
        self.rows = []
        self.left_items = copy.deepcopy(self.original_text_area_descriptions)

    def sort_column(self):
        if len(self.original_text_area_descriptions) == 0:
            return []
        all_columns = self._create_columns()
        self._sort_columns(all_columns)
        return all_columns

    @staticmethod
    def _sort_columns(all_rows):
        if len(all_rows) < 2:
            return all_rows
        total_size = len(all_rows)
        for i in range(total_size - 1):
            for j in range(i + 1, total_size):
                if all_rows[j][0].center_point[0] < all_rows[i][0].center_point[0]:
                    tmp_row = all_rows[j]
                    all_rows[j] = all_rows[i]
                    all_rows[i] = tmp_row

    def _create_columns(self):
        """
        :return:
        """
        random.shuffle(self.left_items)
        all_columns = []
        while True:
            if len(self.left_items) == 0:
                return all_columns
            row = self._build_one_column()
            all_columns.append(row)

    def _build_one_column(self):
        column = [self.left_items.pop()]
        while True:
            is_insert = False
            left_neighbor_index, distance = self._get_top_neighbor(column)
            if distance < self.max_interval:
                tmp_item = self.left_items.pop(left_neighbor_index)
                column.insert(0, tmp_item)
                is_insert = True
            close_item_index, close_distance = self._get_down_neighbor(column)
            if close_distance < self.max_interval:
                tmp_item = self.left_items.pop(close_item_index)
                column.append(tmp_item)
                is_insert = True
            if not is_insert:
                return column

    def _get_top_neighbor(self, column):
        anchor_item = column[0]
        close_distance = 1000
        close_item_index = None
        for index, item in enumerate(self.left_items):
            start_1 = item.box_coordinate[2][0]
            start_2 = item.box_coordinate[3][0]
            end_1 = anchor_item.box_coordinate[0][0]
            end_2 = anchor_item.box_coordinate[1][0]
            if self.is_intersect(end_1, end_2, start_1, start_2):
                anchor_meddle = (anchor_item.box_coordinate[0] + anchor_item.box_coordinate[1]) / 2
                top_meddle = (item.box_coordinate[2] + item.box_coordinate[3]) / 2
                if anchor_meddle[1] + 4 < top_meddle[1]:
                    continue
                distance = get_distance(top_meddle, anchor_meddle)
                if distance < close_distance:
                    close_distance = distance
                    close_item_index = index
        return close_item_index, close_distance

    def _get_down_neighbor(self, column):
        """
        get down neighbor
        :param column:
        :return:
        """
        anchor_item = column[-1]
        close_distance = 1000
        close_item_index = None
        for index, item in enumerate(self.left_items):
            start_1 = anchor_item.box_coordinate[2][0]
            start_2 = anchor_item.box_coordinate[3][0]
            end_1 = item.box_coordinate[0][0]
            end_2 = item.box_coordinate[1][0]
            if self.is_intersect(end_1, end_2, start_1, start_2):
                anchor_meddle = (anchor_item.box_coordinate[2] + anchor_item.box_coordinate[3]) / 2
                down_meddle = (item.box_coordinate[0] + item.box_coordinate[1]) / 2
                if anchor_meddle[1] - 4 > down_meddle[1]:  # if new point`s height less than anchor
                    continue
                distance = get_distance(anchor_meddle, down_meddle)
                if distance < close_distance:
                    close_distance = distance
                    close_item_index = index
        return close_item_index, close_distance

    @staticmethod
    def is_intersect(end_1, end_2, start_1, start_2):
        if end_2 < end_1:
            end_1, end_2 = end_2, end_1
        if start_2 < start_1:
            start_1, start_2 = start_2, start_1
        ra_1 = []
        a_inter_b = False
        b_inter_a = False
        for i in range(int(end_1), int(end_2)):
            if start_1 < i < start_2:
                ra_1.append(i)
        if len(ra_1) / (abs(end_2 - end_1) + 0.01) > 0.3:
            a_inter_b = True
        ra_1 = []
        for i in range(int(start_1), int(start_2)):
            if end_1 < i < end_2:
                ra_1.append(i)
        if len(ra_1) / (abs(start_2 - start_1) + 0.01) > 0.3:
            b_inter_a = True
        if a_inter_b and b_inter_a:
            return True
        return False


if __name__ == '__main__':
    a = [1, 2, 3, 4, 3, 4, 5, 6, 76, 7, 8, 9]
    a.insert(0, 123)
    print(a)
